L’objectif est de mettre en pratique les techniques présentées dans le tutoriel, à partir de nouveaux jeux de données.
Pour cela, on utilise un jeu de données en open-data : les parkings publics géolocalisés situés dans l’agglomération bordelaise. Les données ont été téléchargées sur le site de l’open-data de Bordeaux Métropole et ont été retravaillées pour les besoins de l’exercice (script ici pour plus de détails).
Par ailleurs, notre objectif sera d’étudier la situation du centre-ville de Bordeaux en termes de présence de places de stationnement, de proportion de places adaptées aux personnes à mobilité réduite et au prix de ces places. Le contour géographique du centre-ville de Bordeaux est fourni. À noter qu’il a été créé « à la main » par les auteurs de ce TP, et qu’il ne répond à aucune définition officielle ou urbanistique précise.
Par ailleurs, à la fin de ce TP, une dernière partie consistera à approximer le nombre d’habitants vivant dans le centre-ville de Bordeaux d’après les données Filosofi 2015 carroyées.
Avant de débuter les exercices, on installe tous les packages nécessaires :
dplyrsfbtbmapsfmapview1aws.s3 (seulement si vous travaillez sur le SSPCloud)## Liste des librairies utilisées
packages <- c("dplyr","sf","btb","mapsf","mapview","aws.s3")
## Vérifier si la librairie est installée, si non l'installer, puis la charger
package.check <- lapply(
packages,
FUN = function(x) {
if (!require(x, character.only = TRUE)) {
install.packages(x, dependencies = TRUE)
library(x, character.only = TRUE)
}
}
)Le code ci-dessous permet d’importer les données utilisées dans ce tutoriel. Elles sont stockées sous Minio, dans le « bucket public » : s3/projet-formation/r-lissage-spatial/.
Quelques informations concernant ces jeux de données :
parking.RDS : table de données géolocalisées concernant les parkings publics dans l’agglomération bordelaise. Attention : on parle de parking publics et non de places de stationnements ! Pour chaque parking public, voici les variables renseignées :
ident : identifiant du parking publicexploit : exploitantnp_global : nombre total de places de stationnementnp_pmr : nombre de places de stationnement pour les personnes à mobilité réduiteth_heur : prix horairex : longitudey : latitudeepsg : code EPSG (projection géographique)bordeaux_centre.gpkg : découpage à façon du centre-ville de Bordeaux2.parkings <-
aws.s3::s3read_using(
FUN = base::readRDS,
object = "r-lissage-spatial/parking.RDS",
bucket = bucket
,
opts = list("region" = "")
)
centreBdx <-
aws.s3::s3read_using(
FUN = sf::st_read,
object = "r-lissage-spatial/bordeaux_centre.gpkg",
bucket = bucket
,
opts = list("region" = "")
)Pour information si vous voulez travailler en dehors du SSPCloud, l’importation peut se faire de cette manière :
url_bucket <- "https://minio.lab.sspcloud.fr/"
object <- "r-lissage-spatial/parking.RDS"
download.file(paste0(url_bucket,bucket,"/",object), destfile = "parking.RDS")
parkings <- readRDS("parking.RDS")
object <- "r-lissage-spatial/bordeaux_centre.gpkg"
centreBdx <- st_read(paste0(url_bucket,bucket,"/",object))Reading layer `file3873b8243dc' from data source
`https://minio.lab.sspcloud.fr/projet-formation/r-lissage-spatial/bordeaux_centre.gpkg'
using driver `GPKG'
Simple feature collection with 1 feature and 0 fields
Geometry type: POLYGON
Dimension: XY
Bounding box: xmin: 415676.3 ymin: 6419503 xmax: 419826.9 ymax: 6425297
Projected CRS: RGF93 v1 / Lambert-93
genercartePour visualiser les résultats de vos lissages, on crée une fonction genercarte de cartographie s’appuyant sur le package mapsf s’appuyant sur les éléments vus dans le tutoriel. On pourra réutiliser cette fonction par la suite, et limiter ainsi le nombre de lignes à recopier dans le code à chaque exercice).
Pour importer cette fonction dans votre environnement global, copier-coller et executer le code ci-dessous.
genercarte <- function(sfcarLisse,nomvar,nbreaks=5,zone,titre,epais=0.2){
#'@param sfcarLisse : Table de carreaux portant les valeurs lissées
#'@param nomvar : Nom de la variable lissée à cartographier
#'@param nbreaks : Nombre de classes à représenter sur la carte (avec méthode des quantiles)
#'@param zone : Polygone de la zone d'intérêt (ex : centre de Bordeaux)
#'@param titre : Titre de la carte (chaîne de caracères)
#'@param epais : epaisseur des la grille des carreaux
#'@returns : carte produite avec le package mapsf
mf_init(x=sfcarLisse,theme = "agolalight")
mf_map(x = sfcarLisse,
type = "choro",
var=nomvar,
breaks = "quantile",
nbreaks = nbreaks,
lwd = epais,
leg_pos = "bottomleft2",
add = TRUE)
mf_map(x = st_cast(zone[,c("geom")],"MULTILINESTRING"),
lwd=4,
col="black",add = TRUE)
mf_layout(title = titre,credits = "Insee-DSAU, Bordeaux Métropole, IGN, mapsf")
}Répondre aux questions suivantes :
parkings ?base::summary) ident exploit np_global np_pmr th_heur x y epsg
1 CUBPK95 METPARK 355 8 2.4 417429.7 6424607 2154
2 CUBPK84 KEOLIS 199 5 3.1 418293.2 6426830 2154
3 CUBPK97 KEOLIS 102 12 4.5 410470.1 6428201 2154
4 CUBPK99 INDIGO_PARK 952 20 0.0 418288.3 6426501 2154
5 CUBPK76 KEOLIS 206 5 4.5 414215.2 6430881 2154
6 CUBPK16 METPARK 667 14 2.8 417759.4 6421534 2154
[1] 87
# 87 parkings dans la base
# Absence de valeurs manquantes dans les xy ? => Vrai
sum(is.na(parkings$x))[1] 0
[1] 0
ident exploit np_global np_pmr th_heur
Length:87 Length:87 Min. : 46.0 Min. : 0.00 Min. : 0.000
Class :character Class :character 1st Qu.: 162.0 1st Qu.: 4.00 1st Qu.: 2.400
Mode :character Mode :character Median : 341.0 Median : 7.00 Median : 3.100
Mean : 473.9 Mean : 9.08 Mean : 3.296
3rd Qu.: 528.5 3rd Qu.:10.50 3rd Qu.: 4.050
Max. :3427.0 Max. :57.00 Max. :14.500
x y epsg
Min. :407552 Min. :6414710 Length:87
1st Qu.:415311 1st Qu.:6420763 Class :character
Median :417608 Median :6421969 Mode :character
Mean :416684 Mean :6422432
3rd Qu.:418911 3rd Qu.:6424019
Max. :422710 Max. :6433813
Observer l’emprise du contour du centre-ville de Bordeaux en utilisant la fonction mapview::mapview (avec un fond de carte OpenStreetMap).
sfparkings.mapview.
sf::st_as_sf. Attention à bien renseigner le système de projection des coordonnées xy dans le paramètre crs.
mapview, on additionne les couches vectorielles avec un + : mapview(polygone)+mapview(points).
Dans le cas présent, le petit nombre de parkings ne rend pas indispensable cette phase de carroyage. Elle permet néanmoins de s’approprier un peu plus la structure spatiale des données avec le lissage.
iCellSize <- 1000 correspondant à la taille des carreaux souhaitéscentroides contenant les centroïdes x_centroide et y_centroide des carreaux de 1000m à partir de la table parkings.nbParkings.x_centroide et y_centroide correspondant respectivement aux variables x et y auxquelles :# 1. Taille des carreaux
iCellSize = 1000
# 2. Centroïdes
centroides <- parkings
centroides$x_centroide = centroides$x - (centroides$x %% iCellSize) + (iCellSize / 2)
centroides$y_centroide = centroides$y - (centroides$y %% iCellSize) + (iCellSize / 2)
# 3. Compter le nombre de parkings par carreau
centroides <- centroides %>%
group_by(x=x_centroide,y=y_centroide) %>%
count(name = "nbParkings")
centroides# A tibble: 48 × 3
# Groups: x, y [48]
x y nbParkings
<dbl> <dbl> <int>
1 407500 6421500 4
2 408500 6421500 1
3 410500 6417500 1
4 410500 6424500 2
5 410500 6428500 1
6 411500 6416500 1
7 411500 6421500 1
8 411500 6422500 1
9 412500 6417500 1
10 412500 6418500 1
# … with 38 more rows
# ℹ Use `print(n = ...)` to see more rows
centroides en grille de carreaux et stocker le résultat dans la variable sfcarreaux.mapview en colorant les carreaux différemment selon le nombre de parkings qu’ils contiennent.
btb::dfToGrid permet de créer la grille de carreaux.
st_join par exemple pour réaliser l’intersection.
mapview, on peut utiliser les options :zcol = "nbParkings"col.regions = list("grey","yellow","red")
# 1. Générer la grille
sfcarreaux <- btb::dfToGrid(df = centroides, sEPSG = "2154",
iCellSize = iCellSize)
# 2. Restriction du champ : on ne retient que les carreaux intersectant Bordeaux-centre
sfcarreaux <- sfcarreaux %>% st_join(centreBdx,left = F)
# sfcarreaux <- sfcarreaux[unlist(st_intersects(centreBdx,sfcarreaux)),]centreBdxBuffer.mapviewparkingsBuff.parkings non vectorielle pour garder des colonnes x et y en vue du carroyage.
sf::st_buffer
sf::st_contains ou sf::st_intersects
# 1. Création d'un buffer autour du territoire
marge <- 3000
centreBdxBuffer <- st_buffer(centreBdx, dist = marge)
# 2. Cartographie avec mapview
mapview(centreBdxBuffer,col.region="gray") + mapview(centreBdx)# 3. Repérer les indices des observations contenues le buffer
# puis réduire la base aux seules observations dans le territoire
indiceObsContenues <- unlist(sf::st_contains(centreBdxBuffer, sfparkings))
parkingsBuff <- parkings[indiceObsContenues, ]
parkingsBuff ident exploit np_global np_pmr th_heur x y epsg
1 CUBPK95 METPARK 355 8 2.400000 417429.7 6424607 2154
2 CUBPK84 KEOLIS 199 5 3.100000 418293.2 6426830 2154
4 CUBPK99 INDIGO_PARK 952 20 0.000000 418288.3 6426501 2154
6 CUBPK16 METPARK 667 14 2.800000 417759.4 6421534 2154
7 CUBPK02 INDIGO_PARK 1661 34 2.400000 418008.0 6422279 2154
8 CUBPK81 INDIGO_PARK 879 19 3.600000 419070.6 6420185 2154
9 CUBPK80 INTERPARKING 405 9 2.200000 419585.1 6424611 2154
11 CUBPK47 KEOLIS 46 4 3.296104 422710.0 6422372 2154
19 CUBPK87 URBIS_PARK 158 3 3.200000 418885.5 6422348 2154
21 CUBPK27 METPARK 847 15 2.800000 417987.8 6423092 2154
22 CUBPK79 METPARK 521 11 3.200000 418727.7 6422330 2154
[ reached 'max' / getOption("max.print") -- omitted 52 rows ]
nbObsLisse = 1L dans parkingsBuff. Que représente-t-elle ?sfcarLissegenercarte.btb::kernelSmoothing !
# 1. Nouvelle variable nbObsLisse
parkingsBuff$nbObsLisse <- 1L
#### C'est une variable de "comptage des observations".
# 2. Lissage
rayon <- 1700 # Rayon de lissage
tcar <- 50 # Taille des carreaux de la grille
parkingsLissage <- parkingsBuff[,c("nbObsLisse","x","y")]
sfcarLisse <- btb::kernelSmoothing(dfObservations = parkingsLissage,
sEPSG = "2154",
iCellSize = tcar,
iBandwidth = rayon)
# 3. Filtrage : ne garder que les carreaux intersectant le centre de Bordeaux
sfcarLisse <- sfcarLisse %>% st_join(centreBdx,left = F)lissage_maison <- function(rayon){
sfcarLisse <- btb::kernelSmoothing(dfObservations = parkingsLissage,
sEPSG = "2154",
iCellSize = tcar,
iBandwidth = rayon)
sfcarLisse <- sfcarLisse %>%
st_join(centreBdx,left = F) %>%
mutate(nbObsLisse=nbObsLisse*(1000/tcar)^2)
genercarte(sfcarLisse=sfcarLisse,
nomvar="nbObsLisse",
nbreaks=5,
zone=centreBdx,
titre=paste0("Lissage de la densité de parkings avec un rayon de ",rayon," m"))
}Lisser le nombre de places de stationnement (variable np_global), et non plus le nombre de parkings.
rayon <- 1700
parkingsLissage <- parkingsBuff[,c("np_global","x","y")]
sfcarLisse <- btb::kernelSmoothing(dfObservations = parkingsLissage,
sEPSG = "2154",
iCellSize = tcar,
iBandwidth = rayon)
# Filtrage des carreaux lissés dans Paris
sfcarLisse <- sfcarLisse %>%
st_join(centreBdx,left = F) %>%
mutate(np_global=np_global*(1000/tcar)^2)
# Carte lissée
genercarte(sfcarLisse=sfcarLisse,
nomvar="np_global",
nbreaks=5,
zone=centreBdx,
titre="Lissage des places de stationnement")np_pmr).
parkingsLissage <- parkingsBuff[,c("np_pmr","x","y")]
sfcarLisse <- btb::kernelSmoothing(dfObservations = parkingsLissage,
sEPSG = "2154",
iCellSize = tcar,
iBandwidth = rayon)
# Filtrage des carreaux lissés dans Paris
sfcarLisse <- sfcarLisse %>%
st_join(centreBdx,left = F)%>%
mutate(np_pmr=np_pmr*(1000/tcar)^2)
# Carte lissée
genercarte(sfcarLisse=sfcarLisse,
nomvar="np_pmr",
nbreaks=5,
zone=centreBdx,
titre="Lissage des places de stationnement PMR")kernelSmoothing.
parkingsLissage <- parkingsBuff[,c("nbObsLisse","np_global","x","y")]
sfcarLisse <- btb::kernelSmoothing(dfObservations = parkingsLissage,
sEPSG = "2154",
iCellSize = tcar,
iBandwidth = rayon)
# Création du ratio lissé à partir des numérateur et dénominateur lissés
sfcarLisse <- sfcarLisse %>% mutate(place_par_parking=np_global/nbObsLisse)
sfcarLisse <- sfcarLisse %>% st_join(centreBdx,left = F)
genercarte(sfcarLisse=sfcarLisse,
nomvar="place_par_parking",
nbreaks=5,
zone=centreBdx,
titre="Lissage du nombre de places par parking")parkingsLissage <- parkingsBuff[,c("np_global","np_pmr","x","y")]
sfcarLisse <- btb::kernelSmoothing(dfObservations = parkingsLissage,
sEPSG = "2154",
iCellSize = tcar,
iBandwidth = rayon)
# Création du ratio lissé à partir des numérateur et dénominateur lissés
sfcarLisse$part_pmf <- 100* sfcarLisse$np_pmr/sfcarLisse$np_global
sfcarLisse <- sfcarLisse %>% st_join(centreBdx,left = F)
genercarte(sfcarLisse=sfcarLisse,
nomvar="part_pmf",
nbreaks=5,
zone=centreBdx,
titre="Lissage de la part de places PMR")Lisser le prix moyen d’une heure de stationnement par parking (sans pondérer par le nombre de places)
parkingsLissage <- parkingsBuff[,c("nbObsLisse","th_heur","x","y")]
sfcarLisse <- btb::kernelSmoothing(dfObservations = parkingsLissage,
sEPSG = "2154",
iCellSize = tcar,
iBandwidth = rayon)
sfcarLisse$prix_moyen <- sfcarLisse$th_heur/sfcarLisse$nbObsLisse
sfcarLisse <- sfcarLisse %>% st_join(centreBdx,left = F)
genercarte(sfcarLisse=sfcarLisse,
nomvar="prix_moyen",
nbreaks=5,
zone=centreBdx,
titre="Lissage du prix par parking (sans pondération)")Lisser le prix moyen d’une heure de stationnement (prendre en compte le nombre de places de stationnement par parking).
Pour chaque parking de la base, il faut lisser :
# Création de la variable "multiplication du prix et du nmbre de places" pour chaque parking
parkingsBuff <- parkingsBuff %>% mutate(prix_x_place=np_global*th_heur)
parkingsLissage <- parkingsBuff[,c("np_global","prix_x_place","x","y")]
sfcarLisse <- btb::kernelSmoothing(dfObservations = parkingsLissage,
sEPSG = "2154",
iCellSize = tcar,
iBandwidth = rayon)
# Et on rapporte par le nombre de places lissé.
sfcarLisse <- sfcarLisse %>% mutate(prix_moyen_place=prix_x_place/np_global)
sfcarLisse <- sfcarLisse %>% st_join(centreBdx,left = F)
# Carte lissée
genercarte(sfcarLisse=sfcarLisse,
nomvar="prix_moyen_place",
nbreaks=5,
zone=centreBdx,
titre="Lissage du prix moyen par place de stationnement")Combien d’habitants vivent dans le centre de Bordeaux tel que nous l’avons défini ?
Pour répondre à cette question :
Comme dans le tutoriel, charger la base des données Filosofi 2015 carroyées (grille de 200m) en ne chargeant que les carreaux de la Gironde grâce à l’option query de sf::st_read.
Vérifier les projections cartographiques utilisées puis faire une intersection géographique entre les carreaux de la Gironde et le contour géographique du centre de Bordeaux
Cartographier avec mapview les carreaux du centre de Bordeaux.
Calculer le nombre d’habitants grâce à la variable Ind.
#1. Chargement des données de Filosofi 2015 en Gironde
url_bucket <- "https://minio.lab.sspcloud.fr/"
bucket <- "projet-formation"
object = "r-lissage-spatial/Filosofi2015_carreaux_200m_metropole.gpkg"
st_read_maison <- function(chemin_tab){
requete <- "SELECT IdINSPIRE,Depcom,Ind,Men, Log_soc, geom
FROM Filosofi2015_carreaux_200m_metropole
WHERE SUBSTR(Depcom, 1, 2) IN ('33') "
sf::st_read(chemin_tab, query = requete)
}
# sans s3
car33 <- st_read_maison(paste0(url_bucket,bucket,"/",object))
# avec s3
car33 <-
aws.s3::s3read_using(
FUN = st_read_maison,
object = object,
bucket = bucket
,
opts = list("region" = "")
)# 2. Vérification de la projection
# puis sélection des carreaux intersectant le centre de Bordeaux
head(car33)Simple feature collection with 6 features and 5 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 380298.5 ymin: 6371417 xmax: 462033.2 ymax: 6482152
Projected CRS: RGF93 v1 / Lambert-93
IdINSPIRE Depcom Ind Men Log_soc geom
1 CRS3035RES200mN2536800E3454800 33540 8 4.1 0 MULTIPOLYGON (((380316.5 64...
2 CRS3035RES200mN2441800E3514800 33444 6 2.5 0 MULTIPOLYGON (((448527.4 63...
3 CRS3035RES200mN2419200E3522000 33195 2 0.9 0 MULTIPOLYGON (((457694.4 63...
4 CRS3035RES200mN2435400E3527600 33066 10 4.1 0 MULTIPOLYGON (((461834.2 63...
5 CRS3035RES200mN2434000E3524000 33254 8 3.3 0 MULTIPOLYGON (((458375.3 63...
6 CRS3035RES200mN2422600E3510600 33391 2 1.0 0 MULTIPOLYGON (((446047.2 63...
# Projection 2154 (Lambert93).
carreaux_centreBdx <- car33 %>% st_join(centreBdx,left = F)
# 3. Cartographie des carreaux du centre de Bordeaux
mapview(centreBdx, color = "black", lwd = 6, alpha.regions = 0,legend=F) +
mapview(carreaux_centreBdx, col.regions="#ffff00")# 4. Combien d'habitants dans le centre de Bordeaux ?
cat("Il y a approximativement ",sum(carreaux_centreBdx$Ind), " habitants dans le centre de Bordeaux")Il y a approximativement 133506.5 habitants dans le centre de Bordeaux
Reproductibilité
R version 4.2.1 (2022-06-23)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Big Sur ... 10.16
Matrix products: default
BLAS: /Library/Frameworks/R.framework/Versions/4.2/Resources/lib/libRblas.0.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.2/Resources/lib/libRlapack.dylib
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices datasets utils methods base
other attached packages:
[1] aws.s3_0.3.21 mapview_2.11.0 mapsf_0.5.0 btb_0.1.30.3 sf_1.0-7
[6] dplyr_1.0.9 knitr_1.39
loaded via a namespace (and not attached):
[1] Rcpp_1.0.9 svglite_2.1.0 lattice_0.20-45
[4] leaflet.providers_1.9.0 png_0.1-7 class_7.3-20
[7] assertthat_0.2.1 digest_0.6.29 utf8_1.2.2
[10] aws.signature_0.6.0 R6_2.5.1 leafpop_0.1.0
[13] stats4_4.2.1 evaluate_0.15 e1071_1.7-11
[16] highr_0.9 httr_1.4.3 unilur_0.4.0.9100
[19] pillar_1.8.0 rlang_1.0.4 uuid_1.1-0
[22] curl_4.3.2 raster_3.5-21 jquerylib_0.1.4
[25] rmarkdown_2.14 webshot_0.5.3 stringr_1.4.0
[28] htmlwidgets_1.5.4 munsell_0.5.0 proxy_0.4-27
[31] compiler_4.2.1 xfun_0.31 systemfonts_1.0.4
[34] pkgconfig_2.0.3 base64enc_0.1-3 htmltools_0.5.3
[37] tidyselect_1.1.2 tibble_3.1.8 codetools_0.2-18
[40] fansi_1.0.3 grid_4.2.1 jsonlite_1.8.0
[43] satellite_1.0.4 lifecycle_1.0.1 DBI_1.1.3
[46] magrittr_2.0.3 units_0.8-0 scales_1.2.0
[49] RcppParallel_5.1.5 KernSmooth_2.23-20 cli_3.3.0
[52] stringi_1.7.8 cachem_1.0.6 farver_2.1.1
[55] renv_0.15.5 leaflet_2.1.1 sp_1.5-0
[58] xml2_1.3.3 bslib_0.4.0 brew_1.0-7
[61] generics_0.1.3 vctrs_0.4.1 RColorBrewer_1.1-3
[64] tools_4.2.1 leafem_0.2.0 glue_1.6.2
[67] purrr_0.3.4 crosstalk_1.2.0 fastmap_1.1.0
[70] yaml_2.3.5 colorspace_2.0-3 terra_1.6-5
[73] classInt_0.4-7 sass_0.4.2
mapview est un package de cartographie produisant des résultats proches de leaflet. Il est un peu plus rapide d’utilisation quant il s’agit de produire des résultats simples : notamment, il reprojette automatiquement les objets géographiques que vous souhaitez cartographier. Plus d’informations ici.↩︎
construit manuellement par les auteurs de ce tutoriel en utilisant le Geoportail.↩︎